package tool.soft

import java.io.File
import akka.stream.Materializer
import dao.{MatrixFileDataDao, MissionDao}
import org.joda.time.DateTime
import play.api.mvc.{AnyContent, Request}
import play.twirl.api.Html
import shared.Pojo.PreDealSoftT
import tool.Pojo._
import tool.{FormTool, Tool}
import tool.soft.AllSoft.SoftBT

import scala.collection.immutable.SeqMap
import implicits.Implicits._
import models.Tables._
import play.api.data.FormBinding
import play.api.libs.ws.WSClient
import play.api.i18n.Messages
import utils.Utils
import upickle.default._

/**
 * Created by yz on 16/9/2020
 */
object PreDealSoft extends PreDealSoftT with SoftBT {

  override def getResultHtml(missionId: Int)(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.mission.preDealResult(missionId)
  }

  def getData(workspaceDir: File) = {
    val value = Utils.configFile2Json(workspaceDir)
    value.transform(reader[PreDealData])
  }

  override def getFileInfos(workspaceDir: File, index: Int)(implicit matrixFileDataDao: MatrixFileDataDao, messages: Messages): List[FileInfoData] = {
    val data = getData(workspaceDir)
    val path = workspaceDir.getAbsolutePath.unixPath
    val index = path.lastIndexOf("user")
    val userId = path.drop(index).split("/")(1).toInt
    val names = data.file.mySplit("/")
    val (tags, fileName) = if (names(0) == ("example")) {
      ("other", names(2))
    } else {
      val row = Tool.getMatrixFileData(data.file)
      (row.tags, row.fileName)
    }
    List(
      FileInfoData("AllMet.csv", messages("allMet"), tags = tags, dataFileName = fileName)
    )
  }

  override def produceConfigFile(workspaceDir: File, index: Int)(implicit request: Request[AnyContent], formBinding: FormBinding) = {
    data.lines().toTxtFile(Tool.getCalculateConfigTxtFile(workspaceDir))
  }

  def getArg(implicit request: Request[AnyContent], messages: Messages, formBinding: FormBinding): ujson.Value = {
    val replaceArg = data.replaceMethod match {
      case "knn" => SeqMap(messages("missingValueImputation") -> messages("kNNImputation"), messages("knnKValue") -> data.knn)
      case "min" => SeqMap(messages("missingValueImputation") -> messages("minText"), messages("NthOfTheMinimumValue") -> data.min)
      case "rowMin" => SeqMap(messages("missingValueImputation") -> messages("rowMinText"), messages("NthOfTheMinimumValue") -> data.min)
      case "none" => SeqMap(messages("missingValueImputation") -> messages("skip"))
    }
    val isNormal = if (data.isNormal == "T") "yes" else "no"
    val argMap = SeqMap(messages("coef") -> data.coef) ++ replaceArg ++ SeqMap(messages("execNormalization") -> isNormal)
    writeJs(argMap)
  }

  override def getCommandData(workspaceDir: File, resultDir: File, index: Int): List[CommandData] = {
    val rawDataFile = new File(workspaceDir, "00_AllMet_Raw.txt")
    val configFile = Tool.getCalculateConfigTxtFile(workspaceDir)
    val dataFile = new File(workspaceDir, "04_AllMet.csv")
    val command =
      s"""
         |${Tool.rScript} ${new File(Tool.rPath, "data_header_deal.R").unixPath} --i ${rawDataFile.unixPath}
         |${Tool.rScript} ${new File(Tool.rPath, "data_filter.R").unixPath} --i ${rawDataFile.unixPath} --config ${configFile.unixPath}
         |${Tool.rScript} ${new File(Tool.rPath, "data_replace.R").unixPath}   --config ${configFile.unixPath}
         |${Tool.rScript} ${new File(Tool.rPath, "normal.R").unixPath} --t normal --config ${configFile.unixPath}
         |${Tool.rScript} ${new File(Tool.rPath, "produce_data_file.R").unixPath} --i ${rawDataFile.unixPath}  --config ${configFile.unixPath}
           """.stripMargin
    List(CommandData(workspaceDir, List(command)))
  }

  override def resultDeal(workspaceDir: File, resultDir: File)(implicit ws: WSClient, materializer: Materializer): Unit = {
    val dataFile = new File(workspaceDir, "04_AllMet.csv")
    val destFile = new File(resultDir, "AllMet.csv")
    dataFile.copyTo(destFile)
  }

  override def getHtml(missionName: String, missionId: Option[Int])(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.soft.preDeal(missionName, missionId)
  }

  override def getMission(implicit request: Request[AnyContent], matrixFileDataDao: MatrixFileDataDao, messages: Messages, formBinding: FormBinding): _root_.models.Tables.MissionRow = {
    val argJson = getArg
    val userId = Tool.getUserId
    val finalFile = Tool.getFileNameOrId(userId, data.file)
    MissionRow(id = 0, missionName = s"${data.missionName}", kind = nameStr, userId = userId,
      startTime = new DateTime(), state = "preparing", arg = argJson, input = List(finalFile))
  }

  override def produceInputFile(workspaceDir: File)(implicit request: Request[AnyContent], dao: MyDao, formBinding: FormBinding): Any = {
    implicit val missionDao = dao.missionDao
    implicit val matrixFileDataDao = dao.matrixFileDataDao
    val rawDataFile = new File(workspaceDir, "00_AllMet_Raw.txt")
    Tool.produceRawDataFile(userId, data.file, rawDataFile)
    val newFile = Tool.getFileNameOrId(userId = userId, fileName = data.file)
    val newData = data.copy(file = newFile)
    Utils.t2ConfigFile(workspaceDir, newData)
  }

  override def data(implicit request: Request[AnyContent], formBinding: FormBinding): PreDealData = {
    FormTool.preDealForm.bindFromRequest().get
  }

}

